package com.users.filters;

import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.BooleanUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public final class ResourceServlet extends HttpServlet{
	/**
	 * 资源文件过滤器
	 */
	private static final long serialVersionUID = 5372615627861275900L;
	private static Log log = LogFactory.getLog(ResourceServlet.class);
	private String encoding = null;
	private boolean isdebug = false;
	private static Map<String, String> mimeTypes;
	private static Map<String, byte[]> rescache;

	static {
		mimeTypes = new HashMap<String, String>();
		rescache = new HashMap<String, byte[]>();
	}

	/**
	 * 初始化资源
	 */
	public void init() throws ServletException {
		log.debug("初始化资源文件过滤器......");
		encoding = getInitParameter("encoding");
		isdebug = BooleanUtils.toBoolean(getInitParameter("isdebug"));
		if (encoding == null) encoding = "utf-8";
		mimeTypes.put("js", "text/javascript");
		mimeTypes.put("css", "text/css");
		mimeTypes.put("gif", "image/gif");
		mimeTypes.put("jpg", "image/jpeg");
		mimeTypes.put("jpeg", "image/jpeg");
		mimeTypes.put("jpe", "image/jpeg");
		mimeTypes.put("png", "image/png");
		mimeTypes.put("html", "text");
		mimeTypes.put("swf", "application/x-shockwave-flash");
	}

	public void destroy() {
		super.destroy();
	}

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		String theServletPath = request.getServletPath() + request.getPathInfo();
		String theExtension = StringUtils.right(theServletPath, theServletPath.length() - theServletPath.lastIndexOf(".") - 1);
		URL resource = ResourceServlet.class.getResource(theServletPath);
		String mimeType = mimeTypes.get(theExtension.trim().toLowerCase());
		if (resource != null && mimeType != null) {
			URLConnection urlConnection = resource.openConnection();
			response.setContentType(mimeType);
			byte bytes[] = null;
			if (!isdebug) {
				bytes = (byte[]) rescache.get(theServletPath);
				if (bytes == null) {
					synchronized (rescache) {
						bytes = getResourceBytesWithBuffer(theExtension, urlConnection);
						rescache.put(theServletPath, bytes);
					}
				}
			} else {
				bytes = getResourceBytes(theExtension, urlConnection);
			}
			response.setContentLength(bytes.length);
			try {
				IOUtils.write(bytes, response.getOutputStream());
			} catch (IOException e) {
			}
		} else {
			response.sendError(404);
		}

	}

	private byte[] getResourceBytesWithBuffer(String theExtension, URLConnection urlConnection) {
		java.io.InputStream inputStream = null;
		byte bt[];
		try {
			inputStream = urlConnection.getInputStream();
			ByteArrayOutputStream outStm = new ByteArrayOutputStream();
			IOUtils.copy(new BufferedInputStream(inputStream), outStm);
			outStm.flush();
			byte bytes[] = outStm.toByteArray();
			bt = bytes;
			return bt;
		} catch (IOException e) {
			log.error(e.getMessage(), e);
			throw new RuntimeException(e);
		} finally {
			IOUtils.closeQuietly(inputStream);
		}
	}

	private byte[] getResourceBytes(String theExtension, URLConnection urlConnection) {
		InputStream is = null;
		byte bt[];
		try {
			is = urlConnection.getInputStream();
			bt = IOUtils.toByteArray(is);
			return bt;
		} catch (IOException e) {
			log.error(e.getMessage(), e);
			throw new RuntimeException(e);
		} finally {
			IOUtils.closeQuietly(is);
		}
	}

	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		doGet(req, resp);
	}
}
